﻿/******************************************************************************
* SunnyUI.FrameDecoder 开源TCP、串口数据解码库。
* CopyRight (C) 2022-2023 ShenYongHua(沈永华).
* QQ群：56829229 QQ：17612584 EMail：SunnyUI@qq.com
*
* Blog:   https://www.cnblogs.com/yhuse
* Gitee:  https://gitee.com/yhuse/SunnyUI.FrameDecoder
*
* SunnyUI.FrameDecoder.dll can be used for free under the MIT license.
* If you use this code, please keep this note.
* 如果您使用此代码，请保留此说明。
******************************************************************************
* 文件名称: FixedLengthFrameDecoder.cs
* 文件说明: 固定长度 - 数据帧解码器
* 当前版本: V1.0
* 创建日期: 2022-11-01
*
* 2022-11-01: V1.0.0 增加文件说明
******************************************************************************/

using System;

namespace Sunny.FrameDecoder
{
    /// <summary>
    /// 固定长度 - 数据帧解码器
    /// </summary>
    public class FixedLengthFrameDecoder : BaseByteFrameDecoder
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="frameLength">帧固定长度</param>
        public FixedLengthFrameDecoder(int frameLength)
        {
            if (frameLength <= 0)
            {
                throw new ArgumentNullException(nameof(frameLength), $"Length must be greater than zero.");
            }

            FrameLength = frameLength;
            FrameExceptDataLength = frameLength;
        }

        ///<inheritdoc/>
        public override BaseByteFrameDecoder Clone()
        {
            return new FixedLengthFrameDecoder(FrameLength);
        }

        /// <summary>
        /// 解析完整帧数据
        /// </summary>
        /// <param name="frame">完整帧数据</param>
        /// <returns>解析是否成功</returns>
        public override ByteFrameEventArgs DecodeFrame(ReadOnlySpan<byte> frame)
        {
            return frame.Length == FrameLength ?
                new(this, ByteFrameParams.Empty, frame.ToArray()) :
                new ByteFrameEventArgs(null, ByteFrameParams.Empty, frame.ToArray());
        }

        /// <summary>
        /// 帧固定长度
        /// </summary>
        public int FrameLength { get; }

        /// <summary>
        /// 解码函数
        /// </summary>
        protected override void Decoding()
        {
            while (Cache.WrittenCount >= FrameLength)
            {
                LastDecodedTime = DateTime.Now;
                ByteFrameEventArgs e = new(this, ByteFrameParams.Empty, 0, FrameLength, GetResult(0, FrameLength));
                InvokeOnDecoder(e);
                Cache.Remove(FrameLength);
            }
        }
    }
}
